/*
 * Trip.h
 *
 *  Created on: Dec 27, 2010
 *      Author: Kisho
 */


#ifndef TRIP_H_
#define TRIP_H_
#include <e32cmn.h>
#include <s32std.h>
#include <s32file.h>

#include "Test9Container2View.h"
#include "Settings.h"

class Location
	{
public:
	TBuf<50> name;
	};

class Path
	{
public:
	RArray<int> pathList;
	static Path* NewL()
		{
		Path* self = Path::NewLC();
		CleanupStack::Pop( self );
		return self;
		}
	static Path* NewLC()
		{
		Path* self = new ( ELeave ) Path();
		CleanupStack::PushL( self );
		//self->ConstructL();
		return self;
		}
	//void ConstructL();
private:
	int pathListCount;
	bool stepCounterAppended;

public:
	Location start, end;

	//Walking mode
	int walking;
	int walkingListPointer;
private:
	int nextPoint;
	int previousPoint;
public:
	void ResetWalk()
		{
		walking = 0;
		walkingListPointer = 0;
		nextPoint = pathList[0];
		previousPoint = 0;
		}
	Path()
		{
		pathListCount = 0;
		pathList.Append(0);
		
		//walking mode
		walking = 0;
		walkingListPointer = 0;
		}
	virtual ~Path()
		{
		pathList.Close();
		}
	TInt WalkedSteps()
		{
		return walking;
		}
	TBuf<50> ConsumeStepForward()
		{
		TBuf<50> x;
		walking+=CSettings::theInstance()->stepsPerClick;
		if(walking >= nextPoint)
			{
			if(walkingListPointer+1 >= pathList.Count())
				return end.name;
			
			int val = pathList[walkingListPointer+1];
			if(walkingListPointer+2 < pathList.Count())
				{
				previousPoint = nextPoint;
				nextPoint += pathList[walkingListPointer+2];
				}
			walkingListPointer += 2;

			if(val == -1)
				{
				return _L("Right");
				}
			else if(val == -2)
				{
				return _L("Left");
				}
			}
/*		x.AppendNum(walking);
		x.Append(' ');
		x.AppendNum(nextPoint);
		x.Append(' ');
		x.AppendNum(walkingListPointer);*/
		return x;
		}
	TBuf<50> ConsumeStepBackward()
		{
		TBuf<50> x;
		walking-=CSettings::theInstance()->stepsPerClick;
		if(walking <= previousPoint)
			{
			if(walkingListPointer-1 < 0)
				return start.name;
			
			int val = pathList[walkingListPointer-1];
			if(walkingListPointer-2 >= 0)
				{
				nextPoint = previousPoint;
				previousPoint -= pathList[walkingListPointer-2];
				}
			walkingListPointer -= 2;
			
			if(val == -1)
				{
				return _L("Left");
				}
			else if(val == -2)
				{
				return _L("Right");
				}
			}
/*		x.AppendNum(walking);
		x.Append(' ');
		x.AppendNum(previousPoint);
		x.Append(' ');
		x.AppendNum(walkingListPointer);*/
		return x;
		}
	void Forward()
		{
		pathList[pathListCount] += CSettings::theInstance()->stepsPerClick;
		}
	void Backward()
		{
		pathList[pathListCount] -= CSettings::theInstance()->stepsPerClick;
		
		if(pathList[pathListCount] - CSettings::theInstance()->stepsPerClick < 0)	//mmm .. just a thought.
			pathList[pathListCount] = 0;
		}
	void Right()
		{
		pathList.Append(-1);	//indicating right
		pathList.Append(0);
		pathListCount += 2;
		}
	void Left()
		{
		pathList.Append(-2);	//indicating left
		pathList.Append(0);
		pathListCount += 2;
		}
	TInt TotalSteps()
		{
		TInt totalSteps = 0;
		TInt arrLen = pathList.Count();
		for(int i=0 ; i<arrLen ; i++)
			if(pathList[i] > 0)
				totalSteps += pathList[i];
		return totalSteps;
		}
	Path Reverse()
		{
		Path path;
		TBuf<50> tempname;
		tempname.Append(end.name);
		end.name.Replace(0, end.name.Length(), start.name);
		start.name.Replace(0, start.name.Length(), tempname);
		
		TInt arrLen = pathList.Count();
		TInt arrMiddle = pathList.Count() / 2;
		TInt temp;
		TInt i;
		for(i=0 ; i<arrMiddle ; i++)
			{
			temp = pathList[i];
			pathList[i] = pathList[(arrLen - i) - 1];
			pathList[(arrLen - i) - 1] = temp;
			
			if(pathList[i] < 0)
				pathList[i] = -1 * (3 + pathList[i]);
			
			if(pathList[(arrLen - i) - 1] < 0)
				pathList[(arrLen - i) - 1] = -1 * (3 + pathList[(arrLen - i) - 1]);
			
			}
		if(arrLen % 2 != 0)
			if(pathList[i] < 0)
				pathList[i] = -1 * (3 + pathList[i]);

		return path;
		}
	TBuf<512> ViewPath()
		{
		TBuf<512> trip;
		TInt arrLen = pathList.Count();
		TInt pathListVal;
		TInt totalSteps = 0;
		//This loop is just for debugging purposes.
		//Start Debug Purpose
		/*for(TInt j=0 ; j<arrLen ; j++)
			{
			pathListVal = pathList[j];
			trip.AppendNum(pathListVal);
			trip.Append(' ');
			if(pathListVal == -1)
				{
				//trip.Append(_L(" Right "));
				}
			else if(pathListVal == -2)
				{
				//trip.Append(_L(" Left "));
				}
			else
				{
				//trip.AppendNum(pathListVal);
				totalSteps += pathListVal;
				}
			}
		trip.Append('\n');*/
		//End Debug Purpose
		trip.AppendNum(TotalSteps());
		trip.Append(_L(" steps to "));
		trip.Append(end.name);
		return trip;
		}
	bool WriteLine(RStoreWriteStream outstream)
		{
		outstream.WriteL(_L("\n"));
		return true;
		}
	bool WriteToStream(RStoreWriteStream outstream)
		{
		outstream << start.name;
		
		TInt arrLen = pathList.Count();
		//Write how many lines we are going to write. (this helps us while reading it later).
		outstream.WriteInt32L(arrLen);
		
		for(TInt i=0 ; i<arrLen ; i++)
			{
			outstream.WriteInt32L(pathList[i]);
			}
		
		outstream << end.name;
		
		return true;
		}
	TBuf<50> ReadLine(RStoreReadStream instream)
		{
		TBuf<50> line;
		instream.ReadL(line, '\n');
		return line;
		}
	
	bool ReadFromStream(RStoreReadStream instream)
		{
		instream >> start.name;
		
		if(start.name.Length() == 0)
			return false;
		
		TInt arrLen = instream.ReadInt32L();
		for(TInt i=0 ; i<arrLen ; i++)
			pathList.Append(instream.ReadInt32L());
		
		pathList.Remove(0);	//Solving the Zero bug (there is a wrong zero added at the beginning of the list). 
		
		nextPoint = pathList[0]; //set nextPoint after loading the file to point to the first list element
		previousPoint = 0;
		
		instream >> end.name;
		return true;
		}
	};

class Trip
	{
private:
	TInt totalWalkedSteps;
	bool MergePaths(TInt index1, TInt index2);
public:
	void ResetWalk();
	RPointerArray<Path> paths;
	int pathsListPointer;
	bool IsWalking;
    TInt GetWalkedPercentage();
public:
	Trip();
	virtual ~Trip();
	
	bool InsertNewLocation(TBuf<50> locationName);
	bool DeleteLocation(TBuf<50> locationName);
	bool RenameLocation(TBuf<50> locationName, TBuf<50> newName);	
	bool Save(RFs fsSession);
	bool Load(RFs fsSession, TBuf<50> filename);
	Trip Reverse();
	TBuf<512> ViewTrip();
	TInt TotalSteps();
	TBuf<50> MoveStepForward();
	TBuf<50> MoveStepBackward();
	};

#endif /* TRIP_H_ */

